home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-11-07 | 15.8 KB | 460 lines | [TEXT/CWIE] |
- /*************************************************************************
- **
- ** Apple Macintosh Developer Technical Support
- **
- ** Macintosh ATA Manager Sample
- **
- ** by Brian Bechtel, <devsupport@apple.com>
- ** based on the ATA Manager Sample
- ** by Vinnie Moscaritolo, <vinnie@apple.com>
- ** Apple Developer Technical Support
- **
- ** Created from as much sample code I could find.
- ** with much help from Gary Wilkinson, Rich Schnell and
- ** good ol' Martin Minow
- **
- ** "I never remember how a Macintosh program begins. I just
- ** copy all that boilerplate from some other piece of code I
- ** have lying around."
- ** -- Bill Atkinson, paraphrased.
- **
- ** File:ATA Error Detection.c
- **
- ** Copyright © 1997 Apple Computer, Inc.
- ** All rights reserved.
- **
- **
- ** You may incorporate this sample code into your applications
- ** without restriction, though the sample code has been
- ** provided "AS IS" and the responsibility for its operation is
- ** 100% yours. However, what you are not permitted to do is to
- ** redistribute the source as "DTS Sample Code" after having
- ** made changes. If you're going to re-distribute the source,
- ** we require that you make it clear in the source that the
- ** code was descended from Apple Sample Code, but that you've
- ** made changes.
- **
- *************************************************************************/
-
- //-----------------------------------------------------------------------
- #pragma mark Includes
- //---------------------------------------------------------------------------
- #include <stdio.h>
- #include <stdlib.h>
- #include <ATA.h>
- #ifdef __MWERKS__
- #include <SIOUX.h>
- #endif
-
- //----------------------------------------------------------------------------
- #pragma mark Defines
- //----------------------------------------------------------------------------
-
- //
- // Identifies the bus protocol type.
- //
-
- enum
- {
- kDevUnknown = 0,
- kDevATA = 1,
- kDevATAPI = 2,
- kDevPCMCIA = 3
- };
-
- //
- // Identifies the Socket type.
- //
- enum
- {
- kSocketUnknown = 0,
- kSocketInternal = 1,
- kSocketMediaBay = 2,
- kkSocketPCMCIA = 3
- };
-
- //------------------------------------------------------------------------------------
- #pragma mark Macros
- //------------------------------------------------------------------------------------
-
- #define CLEAR(what) do { \
- register Ptr _ptr = (Ptr) &what; \
- register Size _len = sizeof what; \
- for (; _len > 0; --_len) \
- *_ptr++ = 0; \
- } while (0)
-
- #define RETURN_IF_ERROR(_err_,_str_) if (_err_ != noErr) \
- { printf(_str_, _err_); return (_err_); }
-
- //
- // This is returned by the device in response to an IDENTIFY command (512 bytes).
- //
- typedef struct IdentifyBlock
- { /* Structure of Identify data */
- UInt16 Signature; /* Word 00: Constant value */
- UInt16 NumCyls; /* Word 01: # of cylinders (default mode) */
- UInt16 RSVD0; /* Word 02: Constant value of 0 */
- UInt16 NumHds; /* Word 03: # of heads (default mode) */
- UInt16 TrkBytes; /* Word 04: # of unformatted bytes/track */
- UInt16 SecBytes; /* Word 05: # of unformatted bytes/sector */
- UInt16 NumSecs; /* Word 06: # of sectors/track */
- UInt16 VU0; /* Word 07: Vendor unique */
- UInt16 VU1; /* Word 08: Vendor unique */
- UInt16 VU2; /* Word 09: Vendor unique */
- UInt16 Serial[10]; /* Word 10-19: Serial Number (right-justified) */
- UInt16 BufType; /* Word 20: Buffer Type */
- UInt16 BufSize; /* Word 21: Buffer size,512 byte increments */
- UInt16 NumECC; /* Word 22: # of ECC bytes */
- /* these next 2 fields are left justified */
- UInt16 FirmRev[4]; /* Word 23-26:Firmware revision */
- UInt16 ModelNum[20];/* Word 27-46: Model number */
- UInt16 MultCmds; /* Word 47: R/W multiple commands not impl = 0 */
- UInt16 DblXferFlag;/* Word 48: Double transfer flag */
- UInt16 Capabilities;/* Word 49: LBA, DMA, IORDY support indicator */
- UInt16 Reserved1; /* Word 50: Reserved */
- UInt16 PIOTiming; /* Word 51: PIO transfer timing mode */
- UInt16 DMATiming; /* Word 52: DMA transfer timing mode */
- UInt16 Extension; /* Word 53: extended info support */
- UInt16 CurCylinders;/* Word 54: # of current cylinders */
- UInt16 CurHeads; /* Word 55: # of current heads */
- UInt16 CurSPT; /* Word 56: # of current sectors per track */
- UInt16 CurCapacity[2];/* Word 57-58: current capacity in sectors */
- UInt16 MultSectors;/* Word 59: Multiple sector setting */
- UInt16 LBACapacity[2];/* Word 60-61: total sectors in LBA mode */
- UInt16 SWDMA; /* Word 62: single word DMA support */
- UInt16 MWDMA; /* Word 63: multi word DMA support */
- UInt16 APIOModes; /* Word 64: Advanced PIO Xfr mode supported */
- UInt16 MDMATiming; /* Word 65: Minimum Multiword DMA Xfr Cycle */
- UInt16 RDMATiming; /* Word 66: Recommended Multiword DMA Cycle */
- UInt16 MPIOTiming; /* Word 67: Min PIO XFR Time W/O Flow Control */
- UInt16 PIOwRDYTiming;/* Word 68: Min PIO XFR Time with IORDY flow ctrl */
- UInt16 Reserved[187];/* Word 69-255: Reserved */
- } IdentifyBlock;
-
- //------------------------------------------------------------------------------------
- #pragma mark Prototypes
- //------------------------------------------------------------------------------------
-
- Boolean ATAManagerPresent (void);
- Boolean ATAHardwarePresent (void);
- Boolean TrapAvailable (short theTrap);
- void PrintNumVersion (char *label, NumVersion version );
- OSErr DisplayATAManagerInquiryInfo (void);
-
- OSErr ScanATABusses (void);
- OSErr DisplayATADriveIdentity (UInt32 deviceID );
- void DumpRawBuffer ( UInt8 *bufferPtr, int length );
- char* DrvrRefToName (short refNum);
- Boolean CheckBug1(IdentifyBlock *ibPtr);
- Boolean CheckBug2(IdentifyBlock *ibPtr);
-
- // ---------------------------------------------------------------------------
- //
- // This is the mixed mode stuff needed to call the ATA manager
- // if you are generating CFM code (i.e. if you are compiling for
- // Power PC). The 'ataManager' call is not a publicly exported
- // symbol in InterfaceLib.
- //
- #if GENERATINGCFM
- pascal SInt16 ataManager(ataPB *pb);
-
- #define RESULT_OFFSET(type) \
- ((sizeof(type) == 1) ? 3 : ((sizeof(type) == 2) ? 1 : 0))
- #define TBTrapTableAddress(trapNum) (((trapNum & 0x03FF) << 2) + 0xE00)
-
- pascal SInt16 ataManager(ataPB *pb)
- {
- #ifdef applec
- #if sizeof(SInt16) > 4
- #error "Result types larger than 4 bytes are not supported."
- #endif
- #endif
- long private_result;
-
- private_result = CallUniversalProc(
- *(UniversalProcPtr*)TBTrapTableAddress(0xAAF1),
- kPascalStackBased
- | RESULT_SIZE(SIZE_CODE(sizeof(SInt16)))
- | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(pb))),
- pb);
- return *(((SInt16*)&private_result) + RESULT_OFFSET(SInt16));
- }
- #endif
- // ---------------------------------------------------------------------------
- //
- // Display information about the ATA Busses
- //
- OSErr ScanATABusses (void)
- {
- ataDrvrRegister pb;
- OSErr status;
-
- // Get first device ID (yes you have to do this once)
- CLEAR(pb);
- pb.ataPBFunctionCode = kATAMgrFindDriverRefnum;
- pb.ataPBVers = kATAPBVers1;
- pb.ataPBDeviceID = (UInt32)0x0000ffff;
- status = ataManager((ataPB*) &pb );
-
- // loop through devices
- for (pb.ataPBDeviceID = (UInt32) pb.ataDeviceNextID;
- pb.ataPBDeviceID != 0xff;
- pb.ataPBDeviceID = (UInt32) pb.ataDeviceNextID)
- {
- status = ataManager((ataPB*) &pb );
- RETURN_IF_ERROR(status,
- "ATA Find Driver failed with status 0x%04x\n")
-
- printf("\n-----------------------------------------\n\n");
- printf("Device %d %#s\n",
- pb.ataPBDeviceID, DrvrRefToName(pb.ataDrvrRefNum) );
- DisplayATADriveIdentity(pb.ataPBDeviceID);
- };
- return (status);
- }
-
- // ---------------------------------------------------------------------------
- void main (void)
- // ---------------------------------------------------------------------------
- {
- OSErr status;
-
- #if __MWERKS__
- SIOUXSettings.asktosaveonclose = false;
- #endif
-
- printf("Program to detect potential problems with SCSI disk mode\n\n");
- printf("This program looks at your ATA hard disk inside your PowerBook.\n");
- printf("It does not alter the disk or any data in any way.\n");
- printf("See the technote \"PowerBook HD Upgrades and SCSI Disk Mode\n");
- printf("Compatibility\" for details on the conditions this code tests.\n\n");
- printf("Listing devices on your ATA bus ... \n\n");
-
- // Check for ATA Hardware
- // you should do this before calling the ATAManager, since some
- // early ROMS could indicate an ATA manager without the proper
- // HW, thus causing a crash.
- if (ATAHardwarePresent() == FALSE)
- {
- printf("ATA Hardware is not present on this system\n");
- exit(EXIT_FAILURE);
- }
-
- // Check for ATA Manager
- if (ATAManagerPresent() == FALSE)
- {
- printf("ATA Manager is not present on this system\n");
- exit(EXIT_FAILURE);
- }
-
- // Display ATA Device Info
- status = ScanATABusses();
- if (status != noErr)
- {
- printf("Cannot access ATA Manager: 0x%04x\n", (int) status);
- exit(EXIT_FAILURE);
- }
- }
-
- // ---------------------------------------------------------------------------
- OSErr DisplayATADriveIdentity (UInt32 deviceID)
- // ---------------------------------------------------------------------------
- //
- // Display information about the ATA Identify Info
- //
- {
- ataIdentify pb;
- ataDevConfiguration pb1;
-
- IdentifyBlock buffer;
- OSErr status;
- Boolean bugsExist;
- UInt32 capacity;
-
-
- // Get Driver Configuration
- CLEAR(pb1);
- pb1.ataPBFunctionCode = kATAMgrGetDrvConfiguration;
- pb1.ataPBVers = kATAPBVers2;
- pb1.ataPBDeviceID = deviceID;
-
- status = ataManager((ataPB*) &pb1 );
- RETURN_IF_ERROR(status,
- "ATA GetDrvConfiguration failed with status 0x%04x\n")
-
-
- // Setup Identify block;
- CLEAR(pb);
- pb.ataPBFunctionCode = kATAMgrDriveIdentify;
- pb.ataPBVers = kATAPBVers1;
- pb.ataPBDeviceID = deviceID;
- pb.ataPBFlags = mATAFlagIORead + mATAFlagByteSwap ;
-
- if (pb1.ataDeviceType == kDevATAPI)
- pb.ataPBFlags += mATAFlagProtocol1;
-
- pb.ataPBTimeOut = 100;
- pb.ataPBBuffer = (void*) &buffer;
-
- status = ataManager((ataPB*) &pb );
- if (noErr == status)
- {
- switch(pb1.ataDeviceType){
- case kDevATA:
- case kDevATAPI:
- capacity = (buffer.CurCapacity[1] << 16) |
- buffer.CurCapacity[0];
- printf("This disk has %lu sectors of 512 bytes (0x%08lX in hexadecimal).\n",
- capacity, capacity);
- printf("This is roughly equivalent to %lu000 bytes.", capacity/2);
- bugsExist = CheckBug1(&buffer);
- if (!bugsExist)
- bugsExist = CheckBug2(&buffer);
- if (!bugsExist)
- {
- printf("This drive may be safely used in SCSI\n");
- printf("in SCSI disk mode on a PowerBook 3400,\n");
- printf("2400, 5300, 1400, 190, or Duo 2300.\n");
- }
- break;
- default:
- break;
- }
- }
- return status;
- }
-
- // ---------------------------------------------------------------------------
- Boolean ATAManagerPresent (void)
- // ---------------------------------------------------------------------------
- //
- // returns true if this machine has the ata manager
- //
- {
- return (TrapAvailable(kATATrap));
- }
-
- // ---------------------------------------------------------------------------
- Boolean ATAHardwarePresent (void)
- // ---------------------------------------------------------------------------
- //
- // returns true if this machine has ata hardware
- //
- {
- UInt16 configFlags;
-
- // Hardware configuration flags
- configFlags = LMGetHWCfgFlags();
-
- return (configFlags & 0x0080);
- }
-
- //------------------------------------------------------------------------------------
- #pragma mark -
-
- #define NumToolboxTraps() ( \
- (NGetTrapAddress(_InitGraf, ToolTrap) \
- == NGetTrapAddress(0xAA6E, ToolTrap)) \
- ? 0x200 : 0x400 \
- )
- #define GetTrapType(theTrap) ( \
- (((theTrap) & 0x800) != 0) ? ToolTrap : OSTrap \
- )
-
- // ---------------------------------------------------------------------------
- Boolean TrapAvailable (short theTrap)
- // ---------------------------------------------------------------------------
- // (see Inside Mac VI 3-8)
- {
- TrapType trapType;
-
- trapType = GetTrapType(theTrap);
- if (trapType == ToolTrap)
- {
- theTrap &= 0x07FF;
- if (theTrap >= NumToolboxTraps())
- theTrap = _Unimplemented;
- }
- return (
- NGetTrapAddress(theTrap, trapType)
- != NGetTrapAddress(_Unimplemented, ToolTrap)
- );
- }
-
- // ---------------------------------------------------------------------------
- char* DrvrRefToName(short refNum)
- // ---------------------------------------------------------------------------
- //
- // lookup driver name in table
- //
-
- {
- AuxDCEHandle* UTable =
- (AuxDCEHandle*) LMGetUTableBase();
- DCtlPtr dctl;
- Ptr p;
-
- if(!refNum)
- return ((char*) "\p<none>");
-
- dctl = (DCtlPtr) *UTable[~refNum];
- p = dctl->dCtlDriver;
- if( dctl->dCtlFlags & 0x0040)
- p = (void*) *p;
-
- return ( p?(char*) (p+18):(char*)"\p-Purged-");
- }
-
-
- // ---------------------------------------------------------------------------
- Boolean CheckBug1(IdentifyBlock *ibPtr)
- // ---------------------------------------------------------------------------
- //
- // Check for the first of the two bugs. If a drive reports a capacity that
- // is greater than 4 gigabytes, then you should not use that drive in SCSI
- // disk mode on a 190/2300/1400/5300/3400/2400. Return false if no bug
- // conditions found.
- //
- {
- UInt32 capacity;
- Boolean result = false; // assume no bug
-
- capacity = (ibPtr->CurCapacity[1] << 16) |
- ibPtr->CurCapacity[0];
- if (capacity >= (UInt32)0x00800000)
- {
- printf("\n\n******************************************\n");
- printf("* Warning! This drive is too large to be *\n");
- printf("* used in SCSI disk mode on a PowerBook *\n");
- printf("* 3400, 2400, 5300, 1400, 190, or 2300! *\n");
- printf("******************************************\n\n");
- result = true;
- }
- return result;
- }
-
- // ---------------------------------------------------------------------------
- Boolean CheckBug2(IdentifyBlock *ibPtr)
- // ---------------------------------------------------------------------------
- //
- // Check for the second of the two bugs. If a drive reports a capacity that
- // has a lower word with the top bit set, the last 16 Mb of that drive won't
- // work correctly on the 5300/190/1400/2300. Return false if no bug
- // conditions found.
- //
- {
- Boolean result = false; // assume no bug
-
- if (ibPtr->CurCapacity[0] & 0x8000)
- {
- printf("\n\n******************************************\n");
- printf("* Warning! This drive should not be used *\n");
- printf("* in SCSI disk mode on a PowerBook 5300, *\n");
- printf("* 1400, 190, or Duo 2300! *\n");
- printf("* This drive is safe on a 3400 or 2400. *\n");
- printf("******************************************\n");
- result = true;
- }
- return result;
- }